package com.educate.service.impl;


import cn.hutool.json.JSONUtil;
import com.educate.common.lang.ElasticSearchFiledConstant;
import com.educate.dao.NoteDao;
import com.educate.pojo.Note;
import com.educate.service.NoteService;
import com.educate.util.PageElasticSearchUtil;
import com.educate.util.PageUtil;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;


/**
 * @author xiongyu
 * @date 2021/10/28 20:58
 */

@Service
public class NoteServiceImpl implements NoteService {

    @Autowired
   private NoteDao noteDao;

    /**
     * 笔记表名
     */
    private static final String NOTENAME = "note";

    /**
     * 笔记标题
     */
    private static final String NOTETITLE = "title";

    private static final String USERNAME = "username";

    @Autowired
    private RestHighLevelClient client;

    @Override
    @Transactional(rollbackFor = {RuntimeException.class})
    public long addNote(Note note) {
        note.setUsername(Long.parseLong(SecurityContextHolder.getContext().getAuthentication().getPrincipal().toString()));
        note.setCreatedNoteTime(new Date());
        note.setUpdatedNoteTime(new Date());
        noteDao.addNote(note);
        addNoteToElasticSearch(note);
        return note.getNoteId();
    }

    @Override
    @Transactional(rollbackFor = {RuntimeException.class})
    public boolean deleteNote(int noteId) {
        deleteNoteToElasticSearch(noteId);
        return noteDao.deleteNote(noteId) == 1;
    }

    @Override
    @Transactional(rollbackFor = {RuntimeException.class})
    public boolean updateNote(Note note) {
        note.setUsername(Long.parseLong(SecurityContextHolder.getContext().getAuthentication().getPrincipal().toString()));
        note.setUpdatedNoteTime(new Date());
        addNoteToElasticSearch(note);
        return noteDao.updateNote(note) == 1;
    }


    @Override
    public Note queryNote(int noteId) {
        return noteDao.queryNote(noteId);
    }


    /**
     * 在elasticSearch中通过标题模糊查询
     *
     * @param title
     * @param pageNum
     * @param pageSize
     */
    @Override
    public Map<String, Object> queryNoteByTitle(String title, int pageNum, int pageSize) {
        List<Note> notes = new ArrayList<>();
        SearchRequest request = new SearchRequest(NOTENAME);
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery(NOTETITLE, title);
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery(USERNAME,SecurityContextHolder.getContext().getAuthentication().getPrincipal());
        boolQueryBuilder.must(termQueryBuilder);
        boolQueryBuilder.must(matchQueryBuilder);
        request.source().query(boolQueryBuilder);
        request.source().from(pageNum * pageSize).size(pageSize);
        Long total = null;
        try {
            SearchResponse response = client.search(request, RequestOptions.DEFAULT);
            SearchHits searchHits = response.getHits();

            total = searchHits.getTotalHits().value;
            SearchHit[] hits = searchHits.getHits();

            for (SearchHit hit : hits) {
                String json = hit.getSourceAsString();
                notes.add(JSONUtil.toBean(json, Note.class));
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println(notes);
        return PageElasticSearchUtil.getPageInfo(total, notes);
    }

    @Override
    public Map<String, Object> queryAllNotes(int pageNum, int pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        return PageUtil.getPageInfo((Page) noteDao.queryAllNotes(Long.parseLong(SecurityContextHolder.getContext().getAuthentication().getPrincipal().toString())));
    }

    /**
     * 添加笔记到elasticSearch中
     *
     * @param note
     */
    private void addNoteToElasticSearch(Note note) {
        IndexRequest index = new IndexRequest(ElasticSearchFiledConstant.NOTENAME).id(note.getNoteId() + "");
        index.source(JSONUtil.toJsonStr(note), XContentType.JSON);
        try {
            client.index(index, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void deleteNoteToElasticSearch(int id) {
        DeleteRequest deleteRequest = new DeleteRequest(ElasticSearchFiledConstant.NOTENAME, id + "");
        try {

            client.delete(deleteRequest, RequestOptions.DEFAULT);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
